package queueAmqp

import (
	"encoding/json"
	"fmt"
	"gin/service"
	"gin/transcoder/ffmpeg"
	"gin/validate"
	"github.com/spf13/viper"
	"github.com/streadway/amqp"
	"log"
	"os"
	"strconv"
)

var (
	TranscodeQueueConfig = AmqpConfig{}
	videoFormat          = "mp4"
	fileSaveOverwrite    = true
)

func init() {
	TranscodeQueueConfig.reliable = true
	TranscodeQueueConfig.queue = "transcode_queue"
	TranscodeQueueConfig.exchange = "exchange"
	TranscodeQueueConfig.exchangeName = "transcode_exchange"
	TranscodeQueueConfig.exchangeType = "direct"
	TranscodeQueueConfig.routingKey = "transcode_key"
	TranscodeQueueConfig.consumerTag = "transcode_consumer"
}

// 推送转码参数
func PushTransCodeParam(body []byte) {

	uri := getAmqpUrl()

	if err := publishParam(
		uri,
		TranscodeQueueConfig.exchangeName,
		TranscodeQueueConfig.exchangeType,
		TranscodeQueueConfig.routingKey,
		body,
		TranscodeQueueConfig.reliable,
	); err != nil {
		log.Fatalf("%s", err)
	}
}

func RunTransCodeConsumer() {
	uri := getAmqpUrl()

	NewConsumer(
		uri,
		TranscodeQueueConfig.exchangeName,
		TranscodeQueueConfig.exchangeType,
		TranscodeQueueConfig.queue,
		TranscodeQueueConfig.routingKey,
		TranscodeQueueConfig.consumerTag,
		handleTranscode,
	)
}

// 执行转码
func handleTranscode(deliveries <-chan amqp.Delivery) {

	// ffmpeg 配置
	ffmpegConf := &ffmpeg.Config{
		FfmpegBinPath:   viper.GetString("ffmpeg.ffmpegBinPath"),
		FfprobeBinPath:  viper.GetString("ffmpeg.ffprobeBinPath"),
		ProgressEnabled: true,
	}

	opts := ffmpeg.Options{
		OutputFormat: &videoFormat,
		Overwrite:    &fileSaveOverwrite,
	}

	for d := range deliveries {
		Param := validate.TranscodeVideoParam{}
		json.Unmarshal(d.Body, &Param)

		// 获取视频中间帧缩略图
		midTimeFloat, _ := strconv.ParseFloat(Param.Duration, 64)
		midTimeString := fmt.Sprintf("%.2f", midTimeFloat/2)

		err := ffmpeg.New(ffmpegConf).
			Input(Param.TempPath).
			Output("./"+Param.Path+Param.Md5Name+".jpg").
			GenerateThumbnail(midTimeString, Param.Width, Param.Height, false)

		if err != nil {
			log.Printf(err.Error())
		}

		// 执行转码,写入队列
		progress, err := ffmpeg.
			New(ffmpegConf).
			Input(Param.TempPath).
			Output("./" + Param.Path + Param.Md5Name + ".mp4").
			WithOptions(opts).
			Start(opts)

		if err != nil {
			log.Printf(err.Error())
		}

		for msg := range progress {
			log.Printf("%+v", msg)
		}

		// 更新数据
		err = service.UpdateStatusByMd5Name(Param.Md5Name, "yes")

		// 处理完删除临时文件
		err = os.Remove(Param.TempPath)

		d.Ack(false)
	}

	log.Printf("handle: deliveries channel closed")
}

// 执行提取mp3
func HandleExtractAudioDefaultFormat(sourceFile validate.ConvertAudioFormat) (string, error) {

	// ffmpeg 配置
	ffmpegConf := &ffmpeg.Config{
		FfmpegBinPath:   viper.GetString("ffmpeg.ffmpegBinPath"),
		FfprobeBinPath:  viper.GetString("ffmpeg.ffprobeBinPath"),
		ProgressEnabled: true,
	}
	relativePath := "./" + sourceFile.Path + sourceFile.Md5Name + "." + sourceFile.FileFormat
	_, err := os.Stat(relativePath)
	if err == nil {
		relativePath = "./" + sourceFile.Path + sourceFile.Md5Name + "new_transfer_file." + sourceFile.FileFormat
	}
	if sourceFile.FileFormat == "mp3" {

		err = ffmpeg.New(ffmpegConf).
			Input(sourceFile.TempPath).
			Output(relativePath).
			ConvertAudioFormatToMp3()
	} else if sourceFile.FileFormat == "wav" {

		err = ffmpeg.New(ffmpegConf).
			Input(sourceFile.TempPath).
			Output(relativePath).
			ConvertAudioFormatToWav()
	}

	if err != nil {
		log.Printf(err.Error())
		return "", err
	}
	err = os.Rename(relativePath, "./"+sourceFile.Path+sourceFile.Md5Name+"."+sourceFile.FileFormat)

	return "./" + sourceFile.Path + sourceFile.Md5Name + "." + sourceFile.FileFormat, nil

}
